package stone926.mods.more_enchantments.enchantments;

import net.minecraft.enchantment.Enchantment;
import net.minecraft.enchantment.EnchantmentTarget;
import net.minecraft.entity.*;
import net.minecraft.entity.boss.WitherEntity;
import net.minecraft.entity.mob.CreeperEntity;
import net.minecraft.entity.mob.SkeletonEntity;
import net.minecraft.entity.mob.WitchEntity;
import net.minecraft.entity.mob.WitherSkeletonEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.*;
import net.minecraft.world.World;
import stone926.mods.more_enchantments.MoreEnchantmentsMod;
import stone926.mods.more_enchantments.damage.StoneEntityDamageSource;
import stone926.mods.more_enchantments.interfaces.IEntitySpawnedByFlower;
import stone926.mods.more_enchantments.interfaces.ILivingEntity;
import stone926.mods.more_enchantments.util.EnchantmentUtil;
import stone926.mods.more_enchantments.util.RandomUtil;

public class DecapitationEnchantment extends Enchantment {

  public DecapitationEnchantment() {
    super(Rarity.UNCOMMON, EnchantmentTarget.WEAPON, new EquipmentSlot[]{ EquipmentSlot.MAINHAND });
  }

  public static double getDecapitationProbability(int lvl, Entity target) {
    if (lvl <= 0) return 0;
    return lvl * 0.1 * (target instanceof WitchEntity && ((IEntitySpawnedByFlower) target).isSpawnedByMandala() ? 2.5 : 1);
  }

  @Override
  public int getMinPower(int level) {
    return 5 + 30 * (level - 1);
  }

  @Override
  public int getMaxLevel() {
    return 2;
  }

  @Override
  public boolean isTreasure() {
    return false;
  }

  @Override
  public boolean isAcceptableItem(ItemStack stack) {
    return stack.getItem() instanceof AxeItem || stack.getItem() instanceof TridentItem || super.isAcceptableItem(stack);
  }

  @Override
  public float getAttackDamage(int level, EntityGroup group) {
    return Math.max(0, (level - 1) / 2F);
  }

  @Override
  public void onTargetDamaged(LivingEntity user, Entity target, int level) {
    super.onTargetDamaged(user, target, level);
    RandomUtil.runIfPossible(getDecapitationProbability(level, target), user.getRandom(), () -> decapitate(user, target, false));
  }

  public static void decapitate(LivingEntity user, Entity target, boolean acceptPlayer) {
    if (!acceptPlayer && user.isPlayer()) return;
    if (!(target.isPlayer() && user.isPlayer())
      && target.isAlive()
      && target instanceof LivingEntity livingEntity
    ) {
      boolean damaged = ((ILivingEntity) livingEntity).forceDamage(
        StoneEntityDamageSource.decapitation(user), Integer.MAX_VALUE
      );
      if (damaged && !EnchantmentUtil.hasEquipmentEnchantment(MoreEnchantmentsMod.DESTROY_CURSE, user))
        dropSkullIfCan(target, target.getEntityWorld());
    }
  }

  private static void dropSkull(Item item, Entity entity, World world, boolean isPlayer) {
    ItemStack itemStack = new ItemStack(item, 1);
    if (isPlayer) {
      itemStack.getOrCreateNbt().putString("SkullOwner", entity.getEntityName());
    }
    ItemEntity itemEntity = new ItemEntity(world, entity.getX(), entity.getY(), entity.getZ(), itemStack);
    itemEntity.setToDefaultPickupDelay();
    world.spawnEntity(itemEntity);
  }

  private static void dropSkullIfCan(Entity entity, World world) {
    if (entity.getType().equals(EntityType.ZOMBIE)) {
      dropSkull(Items.ZOMBIE_HEAD, entity, world, false);
    } else if (entity instanceof SkeletonEntity) {
      dropSkull(Items.SKELETON_SKULL, entity, world, false);
    } else if (entity instanceof WitherEntity) {
      for (int i = 0; i < 3; i++) { dropSkull(Items.WITHER_SKELETON_SKULL, entity, world, false); }
    } else if (entity instanceof WitherSkeletonEntity) {
      dropSkull(Items.WITHER_SKELETON_SKULL, entity, world, false);
    } else if (entity instanceof CreeperEntity) {
      dropSkull(Items.CREEPER_HEAD, entity, world, false);
    } else if (entity instanceof PlayerEntity) {
      dropSkull(Items.PLAYER_HEAD, entity, world, true);
    }
  }

}
